package fr.inserm.u674.chcdbweb.model.feed;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;

import fr.inserm.u674.chcdbweb.model.DAO.DAOException;
import fr.inserm.u674.chcdbweb.model.DAO.EAVModalityDAO;
import fr.inserm.u674.chcdbweb.model.DAO.EAVVariableDAO;
import fr.inserm.u674.chcdbweb.model.DTO.EAVModality;
import fr.inserm.u674.chcdbweb.model.DTO.EAVVariable;
import fr.inserm.u674.chcdbweb.model.DTO.Tissue;

public class EAVFeeder extends AbstractFeeder {
	private static EAVFeeder instance;
	private static EAVVariableDAO eavVariableDAO;
	private static EAVModalityDAO eavModalityDAO;

	private EAVFeeder() {
	}

	public static EAVFeeder
		getInstance(EAVVariableDAO eavVariableDAO, EAVModalityDAO eavModalityDAO) {
		if (EAVFeeder.eavVariableDAO == null) EAVFeeder.eavVariableDAO = eavVariableDAO;
		if (EAVFeeder.eavModalityDAO == null) EAVFeeder.eavModalityDAO = eavModalityDAO;
		if (instance == null) instance = new EAVFeeder();
		return instance;
	}

	public void analyzeFileContent(String xlsFile, LinkedHashMap<String, String> importFileInfo)
		throws InvalidFormatException, FileNotFoundException, IOException, FeederException {
		String tmpdir = System.getProperty("java.io.tmpdir");
		File importFile = new File(tmpdir + File.separator + xlsFile);
		Workbook wb = WorkbookFactory.create(new FileInputStream(importFile));
		Integer nSheets = new Integer(wb.getNumberOfSheets());

		if (nSheets != 1) throw new FeederException("The file should only contain one sheet");

		Sheet sheet = wb.getSheetAt(0);
		importFileInfo.put("Number of rows", Integer.toString(sheet.getPhysicalNumberOfRows() - 1));

	}

	@SuppressWarnings("unused")
	private HashMap<String,List<EAVModality>> checkImportSheet(Sheet sheet) throws FeederException {

		HashMap<String,List<EAVModality>> map = new HashMap<String, List<EAVModality>>();
		ArrayList<EAVModality> duplicateModalities = new ArrayList<EAVModality>(); 
		ArrayList<EAVModality> newModalities = new ArrayList<EAVModality>();
		
		
		Row firstRow = sheet.getRow(0);
		int nHeaders = firstRow.getPhysicalNumberOfCells();
		if (nHeaders < 2) {
			throw new FeederException(
				"The import file msut contain at least 2 columns with the first one containing the chcIDs.");
		}

		else {
			int rowPos = 0;
			HashMap<Integer, EAVVariable> varIndices = new HashMap<Integer, EAVVariable>();
			for (Row row : sheet) {
				if (rowPos == 0) {
					int cellPos = 0;
					for (Cell cell : row) {
						if (cellPos > 0) {
							String cellContent = cell.getRichStringCellValue().getString();
							try {
								EAVVariable var = new EAVVariable(cellContent);
								if (!eavVariableDAO.existsByName(var)) {
									throw new FeederException("The variable " + cellContent
										+ " does not exist yet in the database. Every variable"
										+ " you wish to import must be created first via the web"
										+ " interface");
								}
								else {
									varIndices.put(cellPos, eavVariableDAO.find(cellContent));
								}
							}
							catch (DAOException e) {
								throw new FeederException(e);
							}
						}
						cellPos++;
					}
				}
				else {
					int cellPos = 0;
					Tissue tissue = new Tissue(row.getCell(0).getRichStringCellValue().getString());
					for (Cell cell : row) {
						int nCells = row.getPhysicalNumberOfCells();
						if (nCells != nHeaders) {
							throw new FeederException("The line " + rowPos + 1
								+ " contains less cells (" + nCells
								+ ") that the number of headers (" + nHeaders + ")");
						}
						else {
							EAVVariable var = varIndices.get(cellPos);
							EAVModality mod = new EAVModality();
							if (var.getDataType().equalsIgnoreCase("FLOAT")
								|| var.getDataType().equalsIgnoreCase("INT")) {
								Double cellContent = null;
								try {
									cellContent = cell.getNumericCellValue();
								}
								catch (IllegalStateException e1) {
									try {
										Double.parseDouble(cell.getRichStringCellValue()
											.getString());
									}
									catch (NumberFormatException e2) {
										throw new FeederException(
											"Import failed due to improper format of cell in column "
												+ var.getVariableName() + " at line " + rowPos
												+ ". A numeric value is expected for this variable");
									}
								}
								mod.setModality(Double.toString(cellContent));
							}
							else if (var.getDataType().equalsIgnoreCase("VARCHAR")
								|| var.getDataType().equalsIgnoreCase("BOOELAN")) {
								try {
									String cellContent = cell.getRichStringCellValue().getString();
									mod.setModality(cellContent);
								}
								catch (IllegalArgumentException e) {
									throw new FeederException(
										"Import failed due to improper format of cell in column "
											+ var.getVariableName() + " at line " + rowPos
											+ ". A text value is expected for this variable");
								}
							}
							mod.setTissue(tissue);
							mod.setEavVariable(var);
							mod.setDeprecated(false);
							try {
								if(eavModalityDAO.exists(mod,true)){
									duplicateModalities.add(mod);
								}
								else{
									newModalities.add(mod);
								}
								
							}
							catch (DAOException e) {
								throw new FeederException(e);
							}
						}

						cellPos++;
					}
				}

				rowPos++;
			}

			map.put("duplicateModalities", duplicateModalities );
			map.put("newModalities", newModalities);
			return map;
		}

	}
}
